<?php


namespace app\api\controller;


use app\admin\model\BydShopOrder;
use think\facade\Db;
use app\model\Pay as PayMod;
use app\common\controller\Api;
class Wxpay extends Api
{
    /**
     * 无需登录的方法,同时也就不需要鉴权了
     * @var array
     */
    protected $noNeedLogin = ['*'];
    //2创建好订单之后付款的接口
    public function pay($param)
    {

//        $param = $this->request->param();
        //在这里查订单
        if($param['status']==1){
            $user=\app\admin\model\BydUser::find($param['user_id']);
            $orderInfo = BydShopOrder::where('orderid', $param['order_id'])->find();
            $orderNo =$param['order_id'];
        }else{
            $orderInfo=\app\api\model\BydIdentity::find($param['id']);
            $orderNo = date('YmdHis') . round(1000,9999);
        }

        //$wuser = \app\model\Wuser::where('wuser_id', $param['wuser_id'])->find();
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $out_trade_no = 'E' . date("YmdHis") . rand(10000, 99999);
//        $subject=$param['WIDsubject'];
        $data = [
            'appid' => 'wx00e9e5b843259a9d',//wx9e0259b9a3c39453
            'mch_id' => '1584376091',//微信支付的商户号f243537b1fa08381293069d29c30f4da
            'nonce_str' => $this->getRandChar(32),//生成随机指定长度的字符串
            'body' => '订单编号' . $orderNo,
            'out_trade_no' => $orderNo,//订单号
            'total_fee' => 1 * 100,//支付金额
            'spbill_create_ip' => $this->real_ip(),
            'notify_url' => 'http://bao.scwushen.com/index.php/api/notify/cg',//项目支付接口
            'trade_type' => 'JSAPI',
            'openid' => $user['openid']
        ];

        $data['sign'] = $this->sign($data);

        $xml = $this->ToXml($data);

        $response = $this->postXmlCurl($xml, $url);

        $array = $this->xmlstr_to_array($response);// xml转成数组

        if($array['return_code']!='SUCCESS'||isset($array['err_code'])) return ['code'=>-1,'errmsg'=>$array['return_msg']];
        $data=[
            'appid'             =>$array['appid'],
            'nonceStr'       => (string)$array['nonce_str'],
            'partnerid'          =>$array['mch_id'],
            'timeStamp'          =>(string)time(),
            'package'         =>"prepayid={$array['prepay_id']}",
            'signType'        =>'MD5',
            'paySign'              =>(string)$array['sign'],
        ];
        return $data;
//        $wxData = $this->wxPay($array['prepay_id']);//
//        return $wxData;
        return json(['code' => 200, 'msg' => 'ok','data'=>$wxData]);

    }

    //1微信支付接口
    public function wxPay($prepayId)
    {
//        $PAY_WXPAY=C('PAY_WXPAY');
        $data['appId'] = 'wxb1ea3da04e1d0443';
        $data['nonceStr'] = $this->getRandChar(32); // 获取指定长度的随机字符串为支付编号
        $data['package'] = "prepay_id=" . $prepayId;
        $data['signType'] = 'MD5';
        $data['timeStamp'] = time();
        $data['sign'] = $this->getSign($data);//生成签名

        return $data;
    }

    //生成签名
    public function getSign($Obj)
    {
        foreach ($Obj as $k => $v) {
            $Parameters[strtolower($k)] = $v;
        }
//        $PAY_WXPAY=C('PAY_WXPAY');
        $key = 'scmyscmyscmyscmyscmyscmyscmyscmy';  //支付秘钥
        // 签名步骤一：按字典序排序参数
        ksort($Parameters);
        $String = "appId=" . $Obj['appId'] . "&nonceStr=" . $Obj['nonceStr'] . "&package=" . $Obj['package'] . "&signType=MD5&timeStamp=" . $Obj['timeStamp'];
        // 签名步骤二：在string后加入KEY
        $String = $String . "&key=" . $key;
        // 签名步骤三：MD5加密
        $result_ = strtoupper(md5($String));
        return $result_;
    }

    // 获取指定长度的随机字符串
    public function getRandChar($length)
    {
        $str = null;
        $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
        $max = strlen($strPol) - 1;

        for ($i = 0; $i < $length; $i++) {
            $str .= $strPol[rand(0, $max)]; // rand($min,$max)生成介于min和max两个数之间的一个随机整数
        }

        return $str;
    }

    //获取浏览器ip地址
    public function real_ip()
    {
        static $realip;


        if ($realip !== NULL) {
            return $realip;
        }


        if (isset($_SERVER)) {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);


                foreach ($arr as $ip) {
                    $ip = trim($ip);


                    if ($ip != 'unknown') {
                        $realip = $ip;
                        break;
                    }
                }
            } else if (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $realip = $_SERVER['HTTP_CLIENT_IP'];
            } else if (isset($_SERVER['REMOTE_ADDR'])) {
                $realip = $_SERVER['REMOTE_ADDR'];
            } else {
                $realip = '0.0.0.0';
            }
        } else if (getenv('HTTP_X_FORWARDED_FOR')) {
            $realip = getenv('HTTP_X_FORWARDED_FOR');
        } else if (getenv('HTTP_CLIENT_IP')) {
            $realip = getenv('HTTP_CLIENT_IP');
        } else {
            $realip = getenv('REMOTE_ADDR');
        }


        preg_match('/[\\d\\.]{7,15}/', $realip, $onlineip);
        $realip = (!empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0');
        return $realip;
    }

    public function get_client_ip($type = 0, $adv = false)
    {
        $type = $type ? 1 : 0;
        static $ip = NULL;
        if ($ip !== NULL) return $ip[$type];
        if ($adv) {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                $pos = array_search('unknown', $arr);
                if (false !== $pos) unset($arr[$pos]);
                $ip = trim($arr[0]);
            } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $ip = $_SERVER['HTTP_CLIENT_IP'];
            } elseif (isset($_SERVER['REMOTE_ADDR'])) {
                $ip = $_SERVER['REMOTE_ADDR'];
            }
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        // IP地址合法验证
        $long = sprintf("%u", ip2long($ip));
        $ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }

    // 数组转xml
    public function ToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }

    // xml转成数组
    public function xmlstr_to_array($xmlstr)
    {
        //禁止引用外部xml实体

        libxml_disable_entity_loader(true);

        $xmlstring = simplexml_load_string($xmlstr, 'SimpleXMLElement', LIBXML_NOCDATA);

        $val = json_decode(json_encode($xmlstring), true);

        return $val;


    }

    // post https请求，CURLOPT_POSTFIELDS xml格式
    public function postXmlCurl($xml, $url, $second = 30)
    {
        // 初始化curl
        $ch = curl_init();
        // 超时时间
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        // 这里设置代理，如果有的话
        // curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        // curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        // 设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        // 要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        // post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        // 运行curl
        $data = curl_exec($ch);

        // 返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error" . "<br>";
            echo "< a href=' '>错误原因查询</ a></br>";
            curl_close($ch);
            return false;
        }
    }

    //生成签名
    public function sign($Obj)
    {
        foreach ($Obj as $k => $v) {
            $Parameters[strtolower($k)] = $v;
        }
        // 签名步骤一：按字典序排序参数
        ksort($Parameters);
        $String = self::formatBizQueryParaMap($Parameters, false);
        // 签名步骤二：在string后加入KEY
        $String = $String . "&key=" . 'TjRUCktaUcR6RQqCksBtwKRY8KwSTC4M';
        // 签名步骤三：MD5加密
        $result_ = strtoupper(md5($String));
        return $result_;
    }

    // 将数组转成uri字符串
    protected function formatBizQueryParaMap($paraMap, $urlencode)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if ($urlencode) {
                $v = urlencode($v);
            }
            $buff .= strtolower($k) . "=" . $v . "&";
        }
        $reqPar;
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }
    public function Respond () {
        $result = $this->xmlstr_to_array( file_get_contents('php://input') );
        $fp = fopen("text.txt",'a');
        fwrite($fp, json_encode($result)."\n");
        fclose($fp);die;
        if ( isset($result['code']) && $result['code'] != 0 ) return ['Roc_code'=>400];
        $sign = $this->getSign( $result, $this->SignType );
        if ( $result['sign'] == $sign ) return $result;
        return ['Roc_code'=>400];
    }
}